from django.http import JsonResponse
from backend.cews.services import LogService
from backend.cews.services import RepairService
from drf_spectacular.utils import extend_schema
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin,RetrieveModelMixin

from rest_framework.viewsets import GenericViewSet
from backend.cews.services.TaskService import query_repair_order_task_of_order, create_order_task
from utils.autoschema import AutoDocSchema, custom_response_serailizer
from utils.decorators import error_response, request_data 
from backend.cews.models import RepairOrderTask, Log, Parts,RepairOrder
from backend.cews.eform_single import eform_update_user_singlel
from django.db import transaction
from datetime import datetime
from backend.cews.signals import check_repair_order_task
from .serializers import (RepairOrderTaskSerializer)
from rest_framework.response import Response


class RepairOrderTaskViewSet(
    RetrieveModelMixin,
    ListModelMixin,
    # UpdateModelMixin,
    GenericViewSet,
    # CreateModelMixin
):
    serializer_class = RepairOrderTaskSerializer
    queryset = RepairOrderTask.objects.all()

    @extend_schema(responses=custom_response_serailizer(RepairOrderTaskSerializer(many=True)))
    @action(methods=['POST'], schema=AutoDocSchema(), detail=False,url_name='get_repair_order_all_tasks')
    @request_data(keys=[
        'repair_order_id'
    ])
    def get_repair_order_all_tasks(self, request, repair_order_id):
        '''
            desc: Get list of repair order task for a repair order
            json:
                repair_order_id: number
        '''

        try:
            rots = query_repair_order_task_of_order(repair_order_id)
            rots = RepairOrderTaskSerializer(rots, many=True).data
            RepairService.update_repair_order_last_action_date(repair_order_id)
            
            return Response(status=200,
                            data={
                                'code': 1,
                                'data': rots
                            })

        except Exception as e:
            return Response(status=400,
                            data={
                                'code': 0,
                                'message': str(e)
                            })

    @action(detail=False, methods=['post'], schema=AutoDocSchema(), url_name='upldate_repair_order_task_check_user')
    @request_data(keys=['repair_order_task_id', 'check_user_id', 'flow'])
    @error_response()
    def upldate_repair_order_task_check_user(self, request, repair_order_task_id,check_user_id, flow):
        repair_order_task_obj = RepairOrderTask.objects.get(id=repair_order_task_id)
    
        if flow == RepairOrderTask.FlowType.ENDORSE:
            repair_order_task_obj.endorse_user_id = check_user_id
        elif flow == RepairOrderTask.FlowType.VERIFY:
            repair_order_task_obj.verify_user_id = check_user_id

        if repair_order_task_obj.endorse_user_id == repair_order_task_obj.verify_user_id:
            return Response(status=400, data={
                "code": 0,
                "message": "Verify and Endorse users cannot coexist"
            })

        repair_order_task_obj.save()
        eform_update_user_singlel.send(sender=None,instance=repair_order_task_obj)
        return Response(status=200, data={
            "code": 1,
            "message": "ok"
        })

    @action(detail=False, methods=['post'], schema=AutoDocSchema())
    @request_data(keys=['update'])
    @error_response()
    def bulk_update_result(self,request,update):
        '''
            desc: >
                Bulk update repair order task result
                
                ## Request
                
                
                ```
                
                {
                    update = [
                        {id:1,result:'Pass'|'Fail'|'NA'},
                    ]
                }
                
                ```
                
                
                ## Response
                
                
                ```
                
                {
                    'code':1,
                    'message':'Success'
                }
                
                ```
        '''
        
        print(update)
        
        for item in update:
            id = item['id']
            result = item['result']
            rot = RepairOrderTask.objects.get(id=id)
            if result == 'N/A':
                now = None
                user = None
            else:
                now = datetime.now()
                user = request.user
            print(now)
            rot.role_result = result
            rot.done_by = user
            rot.done_by_datetime = now
            rot.save()
        
        return JsonResponse(data={
            'code':1,
            'message':'success',
        },status=200)
        

    @action(methods=['POST'], schema=AutoDocSchema(), detail=False,url_name='create_order_task')
    @request_data(keys=[
        'order_id',
        'name',
        'mtce_type',
        'cur_tab',
        'final_tab',
        'eform_schema_id',
        'verify_user_id',
        'endorse_user_id'
    ])
    def create_order_task(self, request, order_id,name,mtce_type,cur_tab,final_tab,eform_schema_id, verify_user_id, endorse_user_id):

        try:
            rots = create_order_task(
                order_id,
                name,
                mtce_type,
                cur_tab,
                final_tab,
                eform_schema_id,
                verify_user_id,
                endorse_user_id,
                request
            )
            # rots = RepairOrderTaskSerializer(rots, many=True).data
            RepairService.update_repair_order_last_action_date(order_id)
            return Response(status=200,
                            data={
                                'code': 1,
                                # 'data': rots
                            })

        except Exception as e:
            return Response(status=400,
                            data={
                                'code': 0,
                                'message': str(e)
                            })
        
    
    @action(methods=['DELETE'], schema=AutoDocSchema(), detail=False,url_name='remove_order_task')
    @error_response()
    @request_data(keys=[
        'id',
    ])
    def remove_order_task(self, request, id):

        try:
            with transaction.atomic():

                rot = RepairOrderTask.objects.get(pk=id)
                r = rot.repair_order
                r_p = rot.repair_order_part
                if RepairOrderTask.objects.filter(repair_order_id=rot.repair_order_id, stock_code=rot.stock_code, serial_no=rot.serial_no).exclude(id=id).exists():
                    r_p.status = r.status = check_repair_order_task(rot, deleted=True)
                else:
                    r_p.status = r.status = RepairOrder.STATUS.IN_PROCESS

                if rot.done_by is not None:
                    raise ValueError('Task is already done, cannot delete')

                # rots = RepairOrderTaskSerializer(rots, many=True).data
                p = Parts.objects.get(deleted=False, stock_code=rot.stock_code, serial_no=rot.serial_no)

                result = LogService.check_part_is_parent(p)

                new_log = Log(
                    username=request.user.username,
                    log_type=Log.LogType.MAINTENANCE,
                    category_type=Log.CategoryType.TASK,
                    action_type=Log.ActionType.DELETE,
                    action="remove_order_task",
                    payload= request.data,
                    description=f"{rot.name} is deleted",
                    repair_order=rot.repair_order.id,
                    parent_stock_code=result["parent_stock_code"],
                    parent_part=result["parent_serial_no"],
                    part=result["serial_no"],
                    stock_code=result["stock_code"]
                )

                rot.delete()
                new_log.save()
                r.save()
                r_p.save()
                RepairService.update_repair_order_last_action_date(rot.repair_order.id)
        
            
            return Response(status=200,
                            data={
                                'code': 1,
                                # 'data': rots
                            })

        except Exception as e:
            return Response(status=400,
                            data={
                                'code': 0,
                                'message': str(e)
                            })